(function ($) {

	$.fn.test = function (testDataJSON, options) {

		var data = testDataJSON;
		var questions = data.questions;
		var questionsCount = questions.length;
		var currentQuestionIndex = 1;
		var markedQuestions = {};
		var answeredQuestions = {};
		var reviewQuestions = new Array();
		var reviewQuestionsWrapper = {};


		var plugin = this;

		var defaultSettings = {
			nextQuestionText: "Next",
			prevQuestionText: "Previous",
			randomSortQuestions: true,
			draggable: {
				cursor: 'move',
				helper: 'clone',
				revert: 'invalid',
				zIndex: 10000,
				start: null
			}
		};

		plugin.config = $.extend(defaultSettings, options);

		var questionNoDiv = $("<div/>").addClass("col-md-3 currentQuestion");
		var testNameDiv = $("<div/>").addClass("col-md-6").addClass("testName");

		var timeRemainingDiv = $("<div/>").addClass("col-md-3");
		timeRemainingDiv.countdown({
			until: +data.duration,
		});

		var testScreenHeaderDiv = $("<div/>").addClass("row testScreenHeader");
		testScreenHeaderDiv.append(questionNoDiv, testNameDiv);

		$(".test").append(testScreenHeaderDiv);
		var row = $(".test").append($("<div/>").addClass("row main").css("padding-top", "10px"));
		$(".main").append($("<div/>").addClass("col-md-9 testArea"));
		$(".main").append($("<div/>").addClass("col-md-3 reviewSection"));
		$(".reviewSection").append("<div class='box'><div class='box-header'><h4>Review</h4></div><div class='box-content'><div id='reviewRow' class='row' style='padding-top:5px'/></div></div>");

		for (var i = 0; i < questionsCount; i++) {
			$("#reviewRow").append($("<div class='col-lg-3 col-md-3 col-sm-2 col-xs-2'/>").attr("id", "reviewQNo" + i));
			$("#reviewQNo" + i).append($("<button type='button'/>").addClass("btn").addClass("btn-lg").addClass("btn-info").css("font-size", "12px").text(i + 1));
		}

		var selector = "test";
		var viewOnlyMarked = false;
		var reviewedOnce = false;

		plugin.method = {

			setUpTest: function () {
				$(".testName").html(data.info.name);
				var questionsList = $('<ul class="questions"></ul>');

				for (i = 0; i < questionsCount; i++) {
					var question = questions[i];
					var questionLI = $('<li class="question" id="question' + (i + 1) + '"></li>');
					questionLI.append('<h3>' + question.q + '</h3>');

					var inputName = "question" + (i + 1);

					var answers = question.a;

					if (question.type == "SingleSelect" || question.type == "MultiSelect") {
						var answersList = $('<ul class="answers"></ul>');
						for (j in answers) {
							var answer = answers[j];
							var optionId = inputName + "_" + j.toString();
							var optionHolder = $('<div class="option"></div>');
							var input = "";
							if (question.type == "SingleSelect") {
								input = '<input id="' + optionId + '" name="' + inputName + '" type="radio" />';
							} else {
								input = '<input id="' + optionId + '" name="' + inputName + '" type="checkbox" />';
							}
							var optionLabel = '<label style=\"margin-left:5px\" for="' + optionId + '">' + answer.option + '</label>';
							var answerContent = $("<li></li>");
							answerContent.append(optionHolder.append(input, optionLabel));
							answersList.append(answerContent);
						};
						questionLI.append("<br>");
						questionLI.append(answersList).hide();
						questionsList.append(questionLI);
					} else {
						alert("Invalid Question Type " + question.type);
					}
				};

				$(".testArea").append(questionsList);

				var btnHolder = $('<div class="btnHolder control-group" style="margin-bottom:30px"><div class="controls" ><a href="#" class="btn btn-primary prev" style="margin-left:2px">Previous</a><a href="#" class="btn btn-primary next" style="margin-left:2px">Next</a><a href="#" class="btn btn-primary review" style="margin-left:2px">Review</a><a href="#" class="btn btn-primary mark" style="margin-left:2px">Mark</a></div></div>')
				$(".testArea").append(btnHolder);

				$(".next").bind("click", function () {
					plugin.method.showNextQuestion();
				});

				$(".prev").bind("click", function () {
					plugin.method.showPrevQuestion();
				});

				$(".mark").bind("click", function () {
					plugin.method.toggleMarkQuestion();
				});

				$(".review").bind("click", function () {
					plugin.method.reviewQuestions();
				});

				$(".review-marked").live("click", function () {
					viewOnlyMarked = true;

					//Hide the review Screen holder
					$(".testReviewArea").hide();

					//Figure out the first marked question
					for (i = 0; i < questionsCount; i++) {
						if (markedQuestions.hasOwnProperty(i + 1)) {
							plugin.method.goToQuestion(i + 1);
							break;
						}
					}

					$(".currentQuestion").show();
					$('.testArea').show();
				});

			},

			startTest: function () {
				var firstQuestion = $('#' + selector + ' .questions li').first();

				if (firstQuestion.length) {
					firstQuestion.fadeIn(500);
				}
				questionNoDiv.html("Question " + currentQuestionIndex + " of " + questionsCount);
			},

			showNextQuestion: function () {
				if (currentQuestionIndex == questionsCount)
					return;
				if (viewOnlyMarked == false) {
					var currentQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
					currentQuestionIndex++;

					var answersList = currentQuestion.find(".answers");

					//Gave answer for the question
					if (answersList.find("input:checkbox:checked").length > 0 || answersList.find("input:radio:checked").length > 0) {
						if (markedQuestions.hasOwnProperty(currentQuestionIndex - 1)) {
							// Do nothing
						} else {
							$("#reviewQNo" + (currentQuestionIndex - 2)).find("button").removeClass("btn-info").removeClass("btn-success").removeClass("btn-danger").addClass("btn-success");
						}
					} else {
						if (markedQuestions.hasOwnProperty(currentQuestionIndex - 1)) {
							$("#reviewQNo" + (currentQuestionIndex)).find("button").addClass("btn-danger");
						} else {
							$("#reviewQNo" + (currentQuestionIndex)).find("button").addClass("btn-info");
						}
					}

					var nextQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
					if (nextQuestion.length) {
						//Hide the current question
						currentQuestion.hide();
						//Show the next question
						nextQuestion.fadeIn(500);
						nextQuestion.css('opacity', '100');
						plugin.method.updateView();
					}
				} else {
					plugin.method.goToNextMarkedQuestion();
				}

				questionNoDiv.html("Question " + currentQuestionIndex + " of " + questionsCount);
			},

			showPrevQuestion: function () {
				if (currentQuestionIndex == 1)
					return;
				var currentQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
				currentQuestionIndex--;
				var prevQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
				var answersList = currentQuestion.find(".answers");
				//Gave answer for the question
				if (answersList.find("input:checkbox:checked").length > 0 || answersList.find("input:radio:checked").length > 0) {
					if (markedQuestions.hasOwnProperty(currentQuestionIndex)) {
						// Do nothing
					} else {
						$("#reviewQNo" + (currentQuestionIndex)).find("button").removeClass("btn-info").removeClass("btn-success").removeClass("btn-danger").addClass("btn-success");
					}
				} else {
					if (markedQuestions.hasOwnProperty(currentQuestionIndex)) {
						$("#reviewQNo" + (currentQuestionIndex)).find("button").addClass("btn-danger");
					} else {
						$("#reviewQNo" + (currentQuestionIndex)).find("button").addClass("btn-info");
					}
				}


				if (prevQuestion.length) {
					//Hide the current question
					currentQuestion.hide();
					//Show the previous question
					prevQuestion.fadeIn(500);
					prevQuestion.css('opacity', '100');
					plugin.method.updateView();
				}

				questionNoDiv.html("Question " + currentQuestionIndex + " of " + questionsCount);
			},

			goToQuestion: function (questionNumber) {
				//Hide the question that the user was looking at when he clicked on review
				var currentQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
				currentQuestion.hide();

				//Set the question Number as the currentQuestionIndex
				currentQuestionIndex = questionNumber;
				currentQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
				currentQuestion.fadeIn(500);
				currentQuestion.css('opacity', '100');
				plugin.method.updateView();
			},

			goToNextMarkedQuestion: function () {
				for (i = currentQuestionIndex; i < questionsCount; i++) {
					if (markedQuestions.hasOwnProperty(i + 1)) {
						plugin.method.goToQuestion(i + 1);
						break;
					}
				}
			},

			toggleMarkQuestion: function () {
				var markBtn = $(".btnHolder .controls .mark");
				if (markedQuestions.hasOwnProperty(currentQuestionIndex)) {
					delete markedQuestions[currentQuestionIndex];
					markBtn.removeClass("btn-success").addClass("btn-primary");
					markBtn.html("Mark");
					var currentQuestion = $('#' + selector + ' .questions .question').eq(currentQuestionIndex - 1);
					var answersList = currentQuestion.find(".answers");
					var reviewQuesBtn = $("#reviewQNo" + (currentQuestionIndex - 1)).find("button").removeClass("btn-info").removeClass("btn-success").removeClass("btn-danger");

					//Gave answer for the question
					if (answersList.find("input:checkbox:checked").length > 0 || answersList.find("input:radio:checked").length > 0) {
						reviewQuesBtn.addClass("btn-success");
					} else {
						reviewQuesBtn.addClass("btn-info");
					}


				} else {
					markedQuestions[currentQuestionIndex] = "1";
					markBtn.removeClass("btn-primary").addClass("btn-success");
					markBtn.html("Unmark");
					$("#reviewQNo" + (currentQuestionIndex - 1)).find("button").removeClass("btn-info").removeClass("btn-success").removeClass("btn-danger").addClass("btn-danger");
				}
			},

			updateView: function () {
				var markBtn = $(".btnHolder .controls .mark");
				if (markedQuestions.hasOwnProperty(currentQuestionIndex)) {
					markBtn.removeClass("btn-primary").addClass("btn-success");
					markBtn.html("Unmark");
				} else {
					markBtn.removeClass("btn-success").addClass("btn-primary");
					markBtn.html("Mark");
				}
			},

			reviewQuestions: function () {
				//Set to defaults
				viewOnlyMarked = false;
				reviewQuestions = new Array();
				reviewQuestionsWrapper = {};

				for (i = 0; i < questionsCount; i++) {
					var question = questions[i];
					if (markedQuestions.hasOwnProperty(i + 1)) {
						//Question is marked
						question.marked = "yes";
					}
					if (answeredQuestions.hasOwnProperty(i + 1)) {
						question.complete = "yes";
					}
					reviewQuestions.push(question);
				}

				reviewQuestionsWrapper["questions"] = reviewQuestions;

				var src = $("#review-questions-tmpl").html();
				var template = Handlebars.compile(src);

				$('.testArea').hide();
				if (reviewedOnce == false) {
					$(".test").append($("<div/>").addClass("row-fluid testReviewArea"));
					reviewedOnce = true;
				} else {

					$(".testReviewArea").show();
					$(".testReviewArea").empty();
				}
				$(".testReviewArea").load("../test/review_test.html", function () {
					//Hide the current Question	Div in the Header
					$(".currentQuestion").hide();

					$(".testReviewArea #review").append(template(reviewQuestionsWrapper));
				});

			},

			finishTest: function () {
				alert("Finished the test");
			},

		};

		plugin.method.setUpTest();
		plugin.method.startTest();

	};
})(jQuery);